package com.zbiti.anvil.basic.module.business.service.service.impl;

import com.zbiti.anvil.basic.module.business.api.domain.SamplesLeaveDomain;
import com.zbiti.anvil.basic.module.business.api.service.ISamplesLeaveService;
import com.zbiti.anvil.basic.module.business.service.mapper.SamplesLeaveMapper;
import com.zbiti.anvil.wf.api.annotation.WfSupported;
import com.zbiti.anvil.wf.api.domain.param.CompleteTaskParam;
import com.zbiti.anvil.wf.api.domain.param.StartWfInstanceParam;
import com.zbiti.anvil.wf.api.service.IWfService;
import com.zbiti.anvil.wf.engine.runtime.ProcessInstance;
import com.zbiti.anvil.wf.service.template.WfCommonTemplateService;
import com.zbiti.module.common.service.service.impl.BaseServiceImpl;
import com.zbiti.sdk.common.utils.AssertUtils;
import com.zbiti.sdk.common.utils.SessionProxyUtils;
import com.zbiti.sdk.common.utils.StringUtils;

/**
 * 示例：请假申请流程 数据库基础操作接口实现
 *
 * @author Fanyc
 * @date 2022-04-09 18:50:20
 */
@WfSupported(wfCodes = "SAMPLES_LEAVE")
public class SamplesLeaveServiceImpl extends BaseServiceImpl<SamplesLeaveMapper, SamplesLeaveDomain> implements ISamplesLeaveService, WfCommonTemplateService<SamplesLeaveDomain> {

    /**
     * 流程服务
     */
    final private IWfService wfService;

    /**
     * 构造函数
     *
     * @param baseMapper Mapper对象
     * @param wfService
     */
    public SamplesLeaveServiceImpl(SamplesLeaveMapper baseMapper, IWfService wfService) {
        super(baseMapper);
        this.wfService = wfService;
    }

    // 在此处定义业务需要的接口，基础的增删改查接口实现请参考“BaseServiceImpl”类

    @Override
    protected void beforeInsert(SamplesLeaveDomain entity) {
        entity.setUserId((Long) SessionProxyUtils.getUserId());
        entity.setUserName(SessionProxyUtils.getUserName());
        // dictType=samples_leave_status
        entity.setStatus("01");
    }

    /**
     * 查询时权限校验增加现在SQL
     *
     * <p>
     * 帮助文档：基础业务平台 -> 安全机制 -> 数据安全
     * 链接地址：https://anvil.zbiti.cn/anvil-basic-docs/security/data/
     * </p>
     *
     * @param method     方法名
     * @param args       参数列表
     * @param databaseId 数据库类型ID
     * @return 权限过滤字符串
     */
    @Override
    public String dataScopeSelectSql(String method, Object[] args, String databaseId) {
        // 只查看自己的数据
        return super.getSelfUser(null, databaseId);
    }

    //////////////////// IWfStartTemplate Start ////////////////////

    /**
     * 获取流程服务对象
     *
     * @return 流程服务对象
     */
    @Override
    public IWfService getWfService() {
        return this.wfService;
    }

    /**
     * 完成工作流之前
     *
     * <pre>
     *     用于待办处理时，先对业务数据进行处理，
     *     并封装完成待办所需的参数对象进行返回
     * </pre>
     *
     * @param businessDomain 业务参数
     * @return 启动参数
     */
    @Override
    public CompleteTaskParam beforeCompleteTask(SamplesLeaveDomain businessDomain) {
        return null;
    }

    /**
     * 启动流程之前
     *
     * <pre>
     * 用于业务数据的处理，发起流程之前对数据进行修改
     * 同时，将启动流程相关的信息进行封装返回
     * </pre>
     *
     * @param businessDomain 业务参数
     * @return 启动参数
     */
    @Override
    public StartWfInstanceParam beforeStartWfInstance(SamplesLeaveDomain businessDomain) {
        // 1.保存业务数据，由于是从新增/修改页面进入的，所以可能是新增或者更新，根据具体业务场景来判断
        // 如果是新增，则需要将新增成功的ID回写到businessDomain对象中，后面的流程业务Key和更新状态都会用到
        this.insertOrUpdate(businessDomain);

        // 2、组装发起流程参数
        StartWfInstanceParam startWfInstanceParam = new StartWfInstanceParam(businessDomain);
        // 使用ID作为业务key，如果前面没有回写则需要根据业务选择其他的ID
        startWfInstanceParam.setBusinessKey(String.valueOf(businessDomain.getApplyId()));
        startWfInstanceParam.setBusinessSubject("[" + SessionProxyUtils.getUserName() + "]请假流程");
        startWfInstanceParam.setWfCode("SAMPLES_LEAVE");

        // 3、其他需要更新的流程参数，根据业务来添加
        startWfInstanceParam.putParam("leaveDays", businessDomain.getLeaveDays());
        return startWfInstanceParam;
    }

    /**
     * 流程启动成功之后
     *
     * <pre>
     * 流程启动成功之后，可以拿到流程相关的数据，
     * 用于将业务与流程进行绑定处理
     * </pre>
     *
     * @param processInstance 流程实例对象
     * @param businessDomain  业务参数
     */
    @Override
    public void afterStartWfInstance(ProcessInstance processInstance, SamplesLeaveDomain businessDomain) {
        // 流程发起后更新状态
        SamplesLeaveDomain update = new SamplesLeaveDomain();
        update.setApplyId(businessDomain.getApplyId());
        // 审批中
        update.setStatus("02");
        // 根据ID进行状态更新，如果保存时没有回写，则需要根据自己的需要进行更新
        this.updateById(update);
    }



    //////////////////// IWfStartTemplate End ////////////////////

    //////////////////// IWfReStartTemplate Start ////////////////////

    /**
     * 重新提交工作流之前
     *
     * <pre>
     *     用于第一个节点时流程发起人时，
     *     驳回给流程发起人重新编写后再次提交，
     *     同时，组装完成流程信息进行重新提交
     * </pre>
     *
     * @param businessDomain 业务参数
     * @return 启动参数
     */
    @Override
    public CompleteTaskParam beforeRestartWfInstance(SamplesLeaveDomain businessDomain) {
        AssertUtils.assertNotNull(businessDomain, "要提交的申请信息不可以为空");
        AssertUtils.assertNotNull(businessDomain.getApplyId(), "要重新提交的申请ID不可以为空");
        AssertUtils.assertNotNull(businessDomain.getParam("taskId"), "要重新提交的TaskID不可以为空");
        AssertUtils.assertTrue(businessDomain.getLeaveDays() > 0, "要重新申请的请假天数不可以为负数");

        // 1.保存业务数据
        SamplesLeaveDomain update = new SamplesLeaveDomain();
        update.setApplyId(businessDomain.getApplyId());
        update.setLeaveDays(businessDomain.getLeaveDays());
        update.setStatus("02");
        update.setRemark(businessDomain.getRemark());
        this.updateById(update);

        // 2、组装完成待办参数，可以使用审批页面传入的参数也可以自定义
        CompleteTaskParam completeTaskParam = new CompleteTaskParam(businessDomain);
        completeTaskParam.setIsApprove(StringUtils.TRUE);
        completeTaskParam.setTaskId(businessDomain.getParam("taskId").toString());
        completeTaskParam.setApproveComment("重新提交申请");
        // 3、其他需要更新的流程参数，根据业务来添加
        completeTaskParam.putParam("leaveDays", businessDomain.getLeaveDays());
        // 4、返回完成待办参数供模板使用
        return completeTaskParam;

    }

    /**
     * 重新提交工作流，完成驳回发起人的流程，非启动新的流程
     *
     * @param businessDomain 业务参数
     * @return 工作流参数
     */
    @Override
    public CompleteTaskParam restartWfInstance(SamplesLeaveDomain businessDomain) {
        return null;
    }
    //////////////////// IWfReStartTemplate End ////////////////////

}
